package cate.game.pvp.eliterace.simulator;


import cate.game.framework.SelectedTask;
import cate.game.framework.advanced.AdvancedByteAttributes;
import cate.game.framework.advanced.AdvancedLongAttributes;
import cate.game.pvp.eliterace.data.EliteRaceKV;
import cate.game.pvp.eliterace.handler.*;
import cate.game.pvp.eliterace.timer.EliteRaceTimerTask.Settings;

import java.util.Objects;
import java.util.function.Function;
import java.util.function.Supplier;

public abstract class EliteRaceSimulator implements SelectedTask<Settings> {
    private final Supplier<EliteRaceKV> kvSupplier;
    private final Supplier<EliteRaceRecordOperation> recordOperationSupplier;
    private final Supplier<EliteRacePsOperation> psOperationSupplier;
    private final Supplier<EliteRaceFightOperation> fightOperationSupplier;
    private final Supplier<EliteRaceRankRwdOperation> rankRwdOperationSupplier;
    private final Supplier<EliteRaceBetOperation> betOperationSupplier;
    private final Supplier<EliteRaceVideoOperation> videoOperationSupplier;

    public EliteRaceSimulator(Supplier<EliteRaceKV> kvSupplier,
                              Supplier<EliteRaceRecordOperation> recordOperationSupplier,
                              Supplier<EliteRacePsOperation> psOperationSupplier,
                              Supplier<EliteRaceFightOperation> fightOperationSupplier,
                              Supplier<EliteRaceRankRwdOperation> rankRwdOperationSupplier,
                              Supplier<EliteRaceBetOperation> betOperationSupplier,
                              Supplier<EliteRaceVideoOperation> videoOperationSupplier) {
        this.kvSupplier = Objects.requireNonNull(kvSupplier);
        this.recordOperationSupplier = Objects.requireNonNull(recordOperationSupplier);
        this.psOperationSupplier = Objects.requireNonNull(psOperationSupplier);
        this.fightOperationSupplier = Objects.requireNonNull(fightOperationSupplier);
        this.rankRwdOperationSupplier = Objects.requireNonNull(rankRwdOperationSupplier);
        this.betOperationSupplier = Objects.requireNonNull(betOperationSupplier);
        this.videoOperationSupplier = Objects.requireNonNull(videoOperationSupplier);
    }

    public abstract boolean runWith(Settings settings);

    public Function<Settings, Boolean> getSettingsFunction() {
        return this::runWith;
    }

    protected EliteRaceKV getKV() {
        return Objects.requireNonNull(this.kvSupplier.get());
    }

    protected AdvancedLongAttributes getAttributes() {
        return Objects.requireNonNull(getKV().getAttributes());
    }

    protected AdvancedByteAttributes getOpAttributes() {
        return Objects.requireNonNull(getKV().getOpAttributes());
    }

    protected EliteRaceRecordOperation getRecordOperation() {
        return Objects.requireNonNull(this.recordOperationSupplier.get());
    }

    protected EliteRacePsOperation getPsOperation() {
        return Objects.requireNonNull(this.psOperationSupplier.get());
    }

    protected EliteRaceFightOperation getFightOperation() {
        return Objects.requireNonNull(this.fightOperationSupplier.get());
    }

    protected EliteRaceRankRwdOperation getRankRwdOperation() {
        return Objects.requireNonNull(this.rankRwdOperationSupplier.get());
    }

    protected EliteRaceBetOperation getBetOperation() {
        return Objects.requireNonNull(this.betOperationSupplier.get());
    }

    protected EliteRaceVideoOperation getVideoOperation() {
        return Objects.requireNonNull(this.videoOperationSupplier.get());
    }

    @Override
    public void run() {
        // no-op
    }
}
